package model;

import java.sql.SQLException;
import java.util.Observable;

import metar.MetarInfo;
import metar.MetarLogException;
import metar.MetarParseException;
import metar.MetarReader;
import util.Config;
import dao.CityDAO;
import dao.CountryDAO;
import dao.DBException;
import dao.WeatherDAO;
import logger.SimpleLogger;
import logger.LogLevel;

/**
 * Wetter-Model-Objekt
 * 
 * @author Bernd Taube
 * @author Jakobus Boettcher
 * @version 1.0
 * 
 */
public class Model extends Observable {
	public Model() {
		
	}

	/***************************************
	 * PROVIDING DATA TO DB
	 * 
	 * @throws ModelException
	 * @throws SQLException
	 * @throws DBException 
	 ***************************************/

	private void provideWeatherModelToDB(WeatherModel weathermodel)
			throws ModelException, SQLException, DBException {
		if (Config.DEBUG){
			SimpleLogger.log(LogLevel.INFO, "provide weathermodel to db");
		}
		if (weathermodel == null) {
			if (Config.DEBUG){
				SimpleLogger.log(LogLevel.ERROR, "weathermodel is null");
			}
			throw new ModelException("WeatherModel not initialised!");
		}
		new WeatherDAO().insert(weathermodel);
	}

	/***************************************
	 * RETRIEVING DATA FROM DB
	 ***************************************/

	/**
	 * retrieves countries from DB
	 * 
	 * @param country
	 * @throws ModelException
	 * @throws SQLException
	 * @throws DBException 
	 */
	public void retrieveCountriesFromDB() throws ModelException, SQLException, DBException {
		if (Config.DEBUG) {
			SimpleLogger.log(LogLevel.INFO, "getting countries from db");
		}
		sendNotifications(new CountryDAO().getCountries());
	}

	/**
	 * retrieves cities from DB by country name
	 * 
	 * @param country
	 * @throws ModelException
	 * @throws SQLException
	 * @throws DBException 
	 */
	public void retrieveCitiesFromDB(CountryModel country)
			throws ModelException, SQLException, DBException {
		if (Config.DEBUG) {
			SimpleLogger.log(LogLevel.INFO, "retrieving cities for " + country.getName());
		}
		if (country == null) {
			if (Config.DEBUG) {
				SimpleLogger.log(LogLevel.INFO, "getting cities from db");
			}
			throw new ModelException("CountryModel not initialised");
		}
		sendNotifications(new CityDAO().getCities(country.getCountryID()));
	}

	/**
	 * retrieves weather from DB by city name
	 * 
	 * @param country
	 * @throws ModelException
	 * @throws SQLException
	 * @throws MetarParseException
	 * @throws MetarLogException
	 * @throws DBException 
	 */
	public void retrieveWeatherFromDB(CityModel city) throws ModelException,
			SQLException, MetarLogException, MetarParseException, DBException {
		if (Config.DEBUG) {
			SimpleLogger.log(LogLevel.INFO,"retrieving weather for " + city.getName());
		}

		if (city == null) {
			if (Config.DEBUG) {
				SimpleLogger.log(LogLevel.ERROR,"CityModel not initialised");
			}
			throw new ModelException("CityModel not initialised");
		}

		/**
		 * Wetter für gewählte Stadt aus Netz holen und an Datenbank übergeben
		 */
		provideWeatherModelToDB(retrieveWeatherFromNet(city.getCityID()));

		/**
		 * View informieren, dass Datenbereitstehen
		 */
		sendNotifications(new WeatherDAO().getAllWeatherByCity(city.getCityID()));
	}

	public void retrieveCurrentWeatherFromDB(CityModel city)
			throws ModelException, SQLException, MetarLogException,
			MetarParseException, DBException {
		
		if (Config.DEBUG) {
			SimpleLogger.log(LogLevel.INFO,"retrieving current weather for "
					+ city.getCityID());
		}

		if (city == null) {
			if (Config.DEBUG) {
				SimpleLogger.log(LogLevel.ERROR,"CityModel not initialised");
			}
			throw new ModelException("CityModel not initialised");
		}

		/**
		 * Wetter für gewählte Stadt aus Netz holen und an Datenbank übergeben
		 */

		provideWeatherModelToDB(retrieveWeatherFromNet(city.getCityID()));

		/**
		 * View informieren, dass Datenbereitstehen
		 */
		sendNotifications(new WeatherDAO().getAktWeatherByCity(city.getCityID()));
	}

	/**************************************
	 * DATA INPUT
	 **************************************/

	/**
	 * 
	 * get weather data from network interface
	 * 
	 * @throws MetarParseException
	 * @throws MetarLogException
	 */
	private WeatherModel retrieveWeatherFromNet(String id)
			throws MetarLogException, MetarParseException {
		if (Config.DEBUG){
			SimpleLogger.log(LogLevel.INFO, "retrieve weather from net for: "+id);
		}
		MetarInfo.setDebugMode(true);
		return new MetarReader(id).getMetarInfo();
	}

	@Override
	public void notifyObservers() {
		setChanged();
	}

	private void sendNotifications(Object o) {
		setChanged();
		notifyObservers(o);
	}
}